#include "tcp_link.hpp"
#include "epoll_loop.hpp"
#include <string.h>
#include <sstream>
#include <iostream>

using std::cout;
using std::endl;

namespace  rocket
{
tcp_link::tcp_link(int client_fd,epoll_loop *loop)
:_client_fd(client_fd)
,_local_address(local_address())
,_peer_address(peer_address())
,_io(_client_fd.get_socket())
,_loop(loop)
,_user()
{

}
tcp_link::~tcp_link()
{

}
sockaddr_in tcp_link::local_address()
{
    sockaddr_in temp;
    memset(&temp, 0, sizeof(temp));
    socklen_t len=sizeof(temp);
    getsockname(_client_fd.get_socket(), (sockaddr *)&temp,&len);
    return temp;
}

sockaddr_in tcp_link::peer_address()
{
    sockaddr_in temp;
    memset(&temp, 0, sizeof(temp));
    socklen_t len=sizeof(temp);
    getpeername(_client_fd.get_socket(), (sockaddr *)&temp,&len);
    return temp;
}
int tcp_link::receive(string &buff,int max_length)
{
    char temp[max_length];
    int ret=_io.read_line(temp, max_length);
    buff=temp;
    return ret;
}

//给底层的io read套了一层
int tcp_link::read_packet(packet &pac)
{
    int ret=_io.read_packet(pac);
    return ret;
}
int tcp_link::send(const string buff,int length)
{
    cout<<"tcp_link::send length="<<length<<" buff="<<buff<<endl;
    int ret=_io.write_n(buff.c_str(), length);
    cout<<"send "<<ret<<":"<<buff<<endl;
    return ret;
}

int tcp_link::peek(string &buff,int max_length)
{
    char temp[max_length];
    int ret=_io.read_peek(temp, max_length);
    buff=temp;
    return ret;
}


void tcp_link::new_link()
{
    _new(shared_from_this());
    
}

void tcp_link::old_link()
{
    _old(shared_from_this());
}


void tcp_link::close_link()
{
    _close(shared_from_this());
}


void tcp_link::set_callback(function<void (shared_ptr<tcp_link>)> callback_new,
                             function<void (shared_ptr<tcp_link>)> callback_old, 
                             function<void (shared_ptr<tcp_link>)> callback_close)
{
    _new=callback_new;
    _old=callback_old;
    _close=callback_close;
}

string tcp_link::get_link_line()
{
    std::stringstream ss;
    ss<<_local_address.get_ip()<<":"<<_local_address.get_port()
      <<"->"<<_peer_address.get_ip()<<":"<<_peer_address.get_port();
    string temp;
    ss>>temp;
    return temp;    
}


bool tcp_link::link_status()
{
    char buff[10]={0};
    int ret=_io.read_peek(buff, sizeof(buff));
    cout<<ret<<endl;
    if(ret<0)
    {
        perror("read_peek");
    }
    return ret;
}



void tcp_link::shutdown_write()
{
    _client_fd.shutdown_write();
}

void tcp_link::add_send_task(string data)
{
    function<void()>send_task=std::bind(&tcp_link::send,this,data,data.size());
    cout<<"add_send_task"<<" length"<<data.size()<<data<<endl;
    _loop->notify(std::move(send_task));
}
void tcp_link::add_send_task(tlv data)
{
    cout<<"add_send_task :";
    data.print();

    string temp(data.get_tlv_head(),data.get_length()+8);
    cout<<*(int *)temp.c_str()<<" :"<<*(int *)(temp.c_str()+4)<<" :"<<(temp.c_str()+8)<<endl;

    function<void()>send_task=std::bind(&tcp_link::send,this,temp,data.get_length()+8);

    cout<<"add_send_task"<<" length"<<(data.get_length()+8)<<temp<<endl;

    _loop->notify(std::move(send_task));

}

string tcp_link::get_user()
{
    return _user;
}

}//end of namespace rocket


